/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/
#include "ak_lock.h"

/* Linux */
#if 	_TARGET_OS == _OS_GNU
void 	_Semaphore_MInit(_t_sysSemM * pSemM)
{
	pthread_mutexattr_t mutex_attr;
	if(pSemM){
		pthread_mutexattr_init(&mutex_attr);
		pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP);
		pthread_mutex_init(pSemM, &mutex_attr);
		pthread_mutexattr_destroy(&mutex_attr);
		
	}
}


int 	_Semaphore_BTake(_t_sysSemB * pSemB, int timeout)
{
	struct 	timespec 	tvOut;
	struct 	timeval		tvCurr;
	int 				ret;

	ret = -1;	
	pthread_mutex_lock(&((pSemB)->mutex));
	if(timeout >= 0){
		/* Set TimeOut */
		gettimeofday(&tvCurr, NULL);
		tvCurr.tv_usec 	+=  timeout * 1000;
		tvCurr.tv_sec	+=  tvCurr.tv_usec/1000000;
		tvCurr.tv_usec 	%=  1000000;
		
		tvOut.tv_sec 	= tvCurr.tv_sec;
		tvOut.tv_nsec	= tvCurr.tv_usec * 1000;
		
		/* Now Wait, Just Wait ......ooOps. We use this for a Given Delay. */
	   	ret = pthread_cond_timedwait(&((pSemB)->cond), &((pSemB)->mutex), &tvOut);
		if((pSemB)->count == 0){
			ret = -1;
		}
	}
	else{
		/* Wait Forever */
		while((pSemB)->count == 0){
			pthread_cond_wait(&((pSemB)->cond), &((pSemB)->mutex));
		}
		(pSemB)->count = 0;
		ret = 0;
	}
    pthread_mutex_unlock(&((pSemB)->mutex));

	return ret;
}

#endif


unsigned long Sys_Atomic_Inc(unsigned long *v, int i)
{
	static int 		_gSysF_Atomic = 0;
	static _t_sysCS	_gSysL_Atomic;
	unsigned long 	ret;
	if(_gSysF_Atomic == 0){
		SYS_INIT_CS(&_gSysL_Atomic);
		_gSysF_Atomic = 1;
	}
	ret = *v;
	SYS_ENTER_CS(&_gSysL_Atomic);
	*v += i;
	SYS_LEAVE_CS(&_gSysL_Atomic);

	return ret;
}

